package jroguelike.utils;

import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA.
 * User: aimozg
 * Date: 21.07.11
 * Time: 14:53
 */
public class Dice {
	public static final Dice ZERO = new Dice(0, 0, 0);

	public static class StandardDie {
		public static final Dice d6 = new Dice(1, 6, 0);
		public static final Dice d10 = new Dice(1, 10, 0);
		public static final Dice d12 = new Dice(1, 12, 0);
		public static final Dice d20 = new Dice(1, 20, 0);
		public static final Dice d100 = new Dice(1, 100, 0);

		public static int d6() {
			return d6.roll();
		}

		public static int d10() {
			return d10.roll();
		}

		public static int d12() {
			return d12.roll();
		}

		public static int d20() {
			return d20.roll();
		}

		public static int d100() {
			return d100.roll();
		}

		public static boolean d6(int vs) {
			return d6.roll(vs);
		}

		public static boolean d10(int vs) {
			return d10.roll(vs);
		}

		public static boolean d12(int vs) {
			return d12.roll(vs);
		}

		public static boolean d20(int vs) {
			return d20.roll(vs);
		}

		public static boolean d100(int vs) {
			return d100.roll(vs);
		}

		private StandardDie() {
		}
	}

	public final int rolls;
	public final int sides;
	public final int bonus;
	public static Random rng = new Random();

	public Dice(int rolls, int sides, int bonus) {
		this.rolls = rolls;
		this.sides = sides;
		this.bonus = bonus;
	}

	public Dice(int rolls, int sides) {
		this.rolls = rolls;
		this.sides = sides;
		this.bonus = 0;
	}

	private static final Pattern pFull = Pattern.compile("(\\d+)d(\\d+)([+-]\\d+)");
	private static final Pattern pDice = Pattern.compile("(\\d+)d(\\d+)");

	public static Dice parse(String str) throws IllegalArgumentException {
		Matcher matcher = pFull.matcher(str);
		try {
			if (matcher.matches()) {
				return new Dice(Integer.parseInt(matcher.group(1)),
						Integer.parseInt(matcher.group(2)),
						Integer.parseInt(matcher.group(3)));
			} else {
				matcher = pDice.matcher(str);
				if (matcher.matches()) {
					return new Dice(Integer.parseInt(matcher.group(1)),
							Integer.parseInt(matcher.group(2)),
							0);
				} else {
					return new Dice(0, 0, Integer.parseInt(str));
				}
			}
		} catch (NumberFormatException ex) {
			throw new IllegalArgumentException(ex);
		}
	}

	public int roll() {
		return roll(rolls, sides, bonus);
	}

	public boolean roll(int vs) {
		return roll() >= vs;
	}

	public static int roll(int rolls, int sides, int bonus) {
		if (rolls == 1) return rng.nextInt(sides) + bonus;
		int accum = bonus;
		for (int i = 0; i < rolls; i++) accum += rng.nextInt(sides);
		return accum;
	}

	@Override
	public String toString() {
		if (rolls == 0) return String.valueOf(bonus);//Z or -Z
		String d = rolls + "d" + sides;
		if (bonus == 0) return d;//XdY
		if (bonus > 0) return d + "+" + bonus;// XdY+Z
		return d + bonus;// XdY-Z
	}
}
